#include "stdafx.h"
//-------------------------------------------------------------------------------------------------
//DicomFile.cpp  - Dicom Image  file       
//-------------------------------------------------------------------------------------------------
//FreeBSD License
//Copyright 2011 Will Stott All rights reserved.
//
//Redistribution and use in source and binary forms, with or without modification, are
//permitted provided that the following conditions are met:
//
//   1. Redistributions of source code must retain the above copyright notice, this list of
//      conditions and the following disclaimer.
//
//   2. Redistributions in binary form must reproduce the above copyright notice, this list
//      of conditions and the following disclaimer in the documentation and/or other materials
//      provided with the distribution.
//
//THIS SOFTWARE IS PROVIDED BY Will Stott ``AS IS'' AND ANY EXPRESS OR IMPLIED
//WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
//FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL Will Stott OR
//CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
//CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
//SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
//ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
//NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
//ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
//The views and conclusions contained in the software and documentation are those of the
//authors and should not be interpreted as representing official policies, either expressed
//or implied, of Will Stott.
//
//----Authors--------------------------------------------------------------------------------------
//created by: will.stott@ucl.ac.uk Feb 2011
//
//----Comments-------------------------------------------------------------------------------------
//
//-------------------------------------------------------------------------------------------------

#include <stdlib.h>


#include "DicomPart.h"


DicomPart::~DicomPart(void)
{
}


DicomPart::DicomPart(void)
{
	_group.val = 0;
	_element.val = 0;
	_vr.val = 0;

	_pStartData = NULL;
	_DataLength = -1L;

	_buff[0] = '\0';
}

DicomPart::DicomPart(BYTE *pData)
{
	_group.b[0] = *pData;
	_group.b[1] = *(pData +1);

	_element.b[0] = *(pData + 2);
	_element.b[1] = *(pData + 3);

	_vr.b[0] = *(pData+4);
	_vr.b[1] = *(pData+5);

	if ( Is4ByteDataLength() )
	{
		DicomLen32Value len;

		len.b[0] = *(pData+8);
		len.b[1] = *(pData+9);
		len.b[2] = *(pData+10);
		len.b[3] = *(pData+11);

		_DataLength = len.val;	
		_pStartData = pData + DicomPart::HeaderMaxLen;
	}
	else
	{
		DicomLenValue len;

		len.b[0] = *(pData+6);
		len.b[1] = *(pData+7);

		_DataLength = len.val;
		_pStartData = pData+8;
	}
	_buff[0] = '\0';
}

const char *DicomPart::GetVRName()
{
	_buff[0] = _vr.b[0];
	_buff[1] = _vr.b[1];
	_buff[2] = '\0';

	return _buff;
}

const char *DicomPart::GetDataAsString()
{
	strcpy_s(_buff, "(null)");

	BYTE *p = _pStartData;
	int x = 0;
	int maxlen = GetDataTypeMaxStringLength();

	if (maxlen > 0 )	//string data types
	{
		while ((x < _DataLength) && ( x < maxlen))
		{
			_buff[x] = *p;
			x++, p++;
		}
		_buff[x] = '\0';
	}
	else				//binary data types
	{
		if (IsDataInteger())
			_itoa_s(GetDataAsInteger(), _buff, 10);
		if (_vr.val == VR_OB)
			strcpy_s(_buff, "(proprietory data)");
		if (_vr.val == VR_SQ)
			strcpy_s(_buff, "(sequence data)");
		if (_vr.val == VR_OW)
			strcpy_s(_buff, "(pixel data)");
	}
	return &_buff[0];
}

bool DicomPart::IsDataInteger()
{
	bool rc = false;
	if ((_vr.val == VR_UL) || (_vr.val == VR_US))
		rc = true;
	return rc;
}

int DicomPart::GetDataTypeMaxStringLength()
{
	int maxlen = 0;

	if ((_vr.val == VR_UI) || (_vr.val == VR_LO) || ((_vr.val == VR_PN)) )
		maxlen = 64;
	if ((_vr.val == VR_SH) || (_vr.val == VR_AE) || (_vr.val == VR_CS) || (_vr.val == VR_TM) || (_vr.val == VR_DS))
		maxlen = 16;
	if (_vr.val == VR_IS)
		maxlen = 12;
	if (_vr.val == VR_DA)
		maxlen = 8;

	return maxlen;
}

UINT DicomPart::GetDataAsInteger()
{
	UINT rc = -1;

	if ((_vr.val == VR_UL) && (_DataLength == 4))
	{
		DicomDataUL data;

		data.b[0] = *(_pStartData); 
		data.b[1] = *(_pStartData+1);
		data.b[2] = *(_pStartData+2);
		data.b[3] = *(_pStartData+3);

		rc = data.val;
	}
	if ((_vr.val == VR_US) && (_DataLength == 2))
	{
		DicomDataUS data;

		data.b[0] = *(_pStartData); 
		data.b[1] = *(_pStartData+1);

		rc = data.val;
	}
	return rc;
}

bool DicomPart::Is4ByteDataLength()
{
	bool rc = false;

	if ((_vr.b[0] == 'O') && (_vr.b[1] == 'B'))
		return true;
	if ((_vr.b[0] == 'O') && (_vr.b[1] == 'W'))
		return true;
	if ((_vr.b[0] == 'O') && (_vr.b[1] == 'F'))
		return true;
	if ((_vr.b[0] == 'S') && (_vr.b[1] == 'Q'))
		return true;
	if ((_vr.b[0] == 'U') && (_vr.b[1] == 'T'))
		return true;
	if ((_vr.b[0] == 'U') && (_vr.b[1] == 'N'))
		return true;

	return rc;
}


const char *DicomPart::GetTagDescription()
{
	char *rc = "[unknown]";

	if (_group.val == 0x0002)
	{
		if (_element.val == 0x0000)
			return "0x0002;0x0000 group length";
		if (_element.val == 0x0001)
			return "0x0002;0x0001 file meta info version";
		if (_element.val == 0x0002)
			return "0x0002;0x0002 media storage SOP Class UID";
		if (_element.val == 0x0003)
			return "0x0002;0x0003 media storage SOP Instance UID";
		if (_element.val == 0x0010)
			return "0x0002;0x0010 Transfer syntax UID";
		if (_element.val == 0x0012)
			return "0x0002;0x0012 Implementation class UID";
		if (_element.val == 0x0013)
			return "0x0002;0x0013 Implementation version name";
		if (_element.val == 0x0016)
			return "0x0002;0x0016 Source Application Entity Title";
	}
	if (_group.val == 0x0008)
	{
		if (_element.val == 0x0008)
			return "0x0008;0x0008 Image Type";
		if (_element.val == 0x0016)
			return "0x0008;0x0016 SOP Class ID";
		if (_element.val == 0x0018)
			return "0x0008;0x0018 SOP Instance ID";
		if (_element.val == 0x0020)
			return "0x0008;0x0020 Study Date";
		if (_element.val == 0x0021)
			return "0x0008;0x0021 Series Date";
		if (_element.val == 0x0023)
			return "0x0008;0x0023 Content Date";
		if (_element.val == 0x0030)
			return "0x0008;0x0030 Study Time";
		if (_element.val == 0x0031)
			return "0x0008;0x0031 Series Time";
		if (_element.val == 0x0033)
			return "0x0008;0x0033 Content Time";
		if (_element.val == 0x0050)
			return "0x0008;0x0050 Accession Number";
		if (_element.val == 0x0060)
			return "0x0008;0x0060 Modality";
		if (_element.val == 0x0070)
			return "0x0008;0x0070 Manufacturer";
		if (_element.val == 0x0080)
			return "0x0008;0x0080 Institution Name";
		if (_element.val == 0x0090)
			return "0x0008;0x90 Referring Physician Name";
		if (_element.val == 0x1010)
			return "0x0008;0x1010 Station Name";
		if (_element.val == 0x1030)
			return "0x0008;0x1030 Study Description";
		if (_element.val == 0x1070)
			return "0x0008;0x1070 Operator Name";
		if (_element.val == 0x1090)
			return "0x0008;0x1090 Manufacturer Model Name";
	}
	if (_group.val == 0x0010)
	{
		if (_element.val == 0x0010)
			return "0x0010;0x0010 Patient Name";
		if (_element.val == 0x0020)
			return "0x0010;0x0020 Patient ID";
		if (_element.val == 0x0030)
			return "0x0010;0x0030 Patient Date of Birth";
		if (_element.val == 0x0040)
			return "0x0010;0x0040 Patient Sex";
	}
	if (_group.val == 0x0018)
	{
		if (_element.val == 0x1000)
			return "0x0018;0x1000 Device Serial Number";
		if (_element.val == 0x6011)
			return "0x0018;0x1000 Sequence of Ultrasound Region";
	}
	if (_group.val == 0x0020)
	{	
		if (_element.val == 0x000D)
			return "0x0020;0x000D Study Instance UID";
		if (_element.val == 0x000E)
			return "0x0020;0x000E Series Instance UID";
		if (_element.val == 0x0010)
			return "0x0020;0x0010 Study ID";
		if (_element.val == 0x0011)
			return "0x0020;0x0011 Series Number";
		if (_element.val == 0x0013)
			return "0x0020;0x0013 Instance Number";
		if (_element.val == 0x0020)
			return "0x0020;0x0020 Patient Orientation";
	}
	if (_group.val == 0x0028)
	{	
		if (_element.val == 0x0002)
			return "0x0028;0x0002 Samples for Pixel";
		if (_element.val == 0x0004)
			return "0x0028;0x0004 Photometric Interpretation";
		if (_element.val == 0x0006)
			return "0x0028;0x0006 Planar Configuration";
		if (_element.val == 0x0010)
			return "0x0028;0x0010 Rows";
		if (_element.val == 0x0011)
			return "0x0028;0x0011 Columns";
		if (_element.val == 0x0100)
			return "0x0028;0x0100 Bits Allocated";
		if (_element.val == 0x0101)
			return "0x0028;0x0101 Bits Stored";
		if (_element.val == 0x0102)
			return "0x0028;0x0102 High Bit";
		if (_element.val == 0x0103)
			return "0x0028;0x0103 Pixel Representation";
		if (_element.val == 0x1050)
			return "0x0028;0x1050 Window Centre";
		if (_element.val == 0x1051)
			return "0x0028;0x1051 Window Width";
	}
	if (_group.val == 0x7FDF)
	{	
		if (_element.val == 0x0010)
			return "0x7FDF;0x0010 Proprietary Data";
		if (_element.val == 0x1001)
			return "0x7FDF;0x1001 Proprietary Data";
	}
	if (_group.val == 0x7FE0)
	{	
		if (_element.val == 0x0010)
			return "0x7FE0;0x0010 Pixel Data";
	}
	return rc;
}





//-------------------------------------------------------------------------------------------------
//			E N D   O F   F I L E
//-------------------------------------------------------------------------------------------------